/************************************************************
 Copyright (C), 2017, Leon, All Rights Reserved.
FileName: get_if_addr.c
Description: get interface address
Author: Leon
Version: 1.0
Date: 
Function:

History:
<author>    <time>  <version>   <description>
Leon
 ************************************************************/

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>

int cale_prefix_len(struct in6_addr *mask)
{
    int i = 0;
    int len = 0;
    int u = 0;

    for(i = 0; i < 16; i++)
    {
        u = mask->s6_addr[i];
        if(ffs(u) > 0)
        {
            len += 9 - ffs(u);
        }
        else
        {
            break;
        }
    }

    return len;
}

int get_if_addr6(char *ifname, struct sockaddr_in6 *list, int len)
{   
    struct ifaddrs *ifaddr, *ifa;   
    int cnt = 0;
    char ip_str[64];

    if(!ifname || !list || !len)
        return 0;

    if (-1 == getifaddrs(&ifaddr))
    {
        perror("getifaddrs");
        return -1; 
    }

    for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) 
    {       
		printf("ifname=[%s]\n", ifa->ifa_name ? ifa->ifa_name:"");
        if(ifa->ifa_name && !strcmp(ifa->ifa_name, ifname) &&
                ifa->ifa_addr->sa_family == AF_INET6)
        {   
            if(cnt > len)
                break;
            memcpy(&list[cnt], ifa->ifa_addr, sizeof(struct sockaddr_in6));
            inet_ntop(AF_INET6, &list[cnt].sin6_addr, ip_str, sizeof(ip_str));
            printf("%s [%d] ip addr [%s]\n", ifname, cnt, ip_str);
            int i = 0;
            for(i =0 ; i < 16; i++)
            {
                printf("%02x ",  (((struct sockaddr_in6*)(ifa->ifa_netmask))->sin6_addr).s6_addr[i] );
            }
            printf("\n");
            printf("mask len: %d\n", cale_prefix_len(&((struct sockaddr_in6*)(ifa->ifa_netmask))->sin6_addr));
            inet_ntop(AF_INET6, &((struct sockaddr_in6*)(ifa->ifa_netmask))->sin6_addr, ip_str, sizeof(ip_str));
            printf("%s [%d] %s [netmask]\n", ifname, cnt, ip_str);
            cnt++;
        }
    }   
    freeifaddrs(ifaddr);      
    return cnt;
}


int main(int argc, char *argv[])
{
    char buf[256] = {0};

    struct sockaddr_in6 *list = malloc(16 * sizeof(struct sockaddr_in6));
    get_if_addr6(argv[1], list, 16);
    return 0;
}
